package com.atguigu.tingshu.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.CategoryFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.AlbumIndexRepository;
import com.atguigu.tingshu.search.repository.SuggestIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {
    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;
    @Autowired
    private CategoryFeignClient categoryFeignClient;
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private AlbumIndexRepository albumIndexRepository;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    private ElasticsearchClient elasticsearchClient;
    @Autowired
    private SuggestIndexRepository suggestIndexRepository;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void upperAlbum(Long albumId) {
        // 创建AlbumInfoIndex对象来封装从各个服务获取的数据
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();

        // 异步获取专辑信息
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            // 调用专辑信息服务，获取专辑详情
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfoById(albumId);
            // 校验专辑信息是否为空
            Assert.notNull(albumInfoResult, "专辑返回结果为空");
            AlbumInfo albumInfo = albumInfoResult.getData();
            Assert.notNull(albumInfo, "专辑为空");
            // 将专辑信息属性复制到albumInfoIndex
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);

            // 处理专辑属性值列表，转换并设置到albumInfoIndex
            List<AlbumAttributeValue> albumAttributeValueList = albumInfo.getAlbumAttributeValueVoList();
            List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueList.stream().map(albumAttributeValue -> {
                AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                return attributeValueIndex;
            }).toList();
            albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
            return albumInfo;
        }, threadPoolExecutor).exceptionally(ex -> {
            // 异常处理，返回空的AlbumInfo对象
            return new AlbumInfo();
        });

        // 异步获取分类信息
        CompletableFuture<Void> categoryCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            // 调用分类服务，获取分类视图
            Result<BaseCategoryView> categoryViewResult = categoryFeignClient.getCategoryView(albumInfo.getCategory3Id());
            BaseCategoryView categoryView = categoryViewResult.getData();
            // 校验分类信息是否为空
            Assert.notNull(categoryView, "获取分类信息失败");
            // 设置分类信息到albumInfoIndex
            albumInfoIndex.setCategory1Id(categoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(categoryView.getCategory2Id());
            albumInfoIndex.setCategory3Id(categoryView.getCategory3Id());

        }, threadPoolExecutor).exceptionally(ex -> {
            // 异常处理
            return null;
        });

        // 异步获取用户信息
        CompletableFuture<Void> userCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            // 调用用户服务，获取用户信息
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfo(albumInfo.getUserId());
            // 校验用户信息是否为空
            Assert.notNull(userInfoVoResult, "远程调用获取用户信息失败");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "获取用户信息失败");
            // 设置用户昵称到albumInfoIndex
            albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
        }, threadPoolExecutor).exceptionally(ex -> {
            // 异常处理
            return null;
        });

        // 异步获取统计信息
        CompletableFuture<Void> statCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            // 调用专辑信息服务，获取专辑统计信息
            Result<AlbumStatVo> albumStatResult = albumInfoFeignClient.getAlbumStat(albumId);
            AlbumStatVo albumStatVo = albumStatResult.getData();
            // 校验统计信息是否为空
            Assert.notNull(albumStatVo, "获取统计信息失败");
            // 设置统计信息到albumInfoIndex
            albumInfoIndex.setPlayStatNum(albumStatVo.getPlayStatNum());
            albumInfoIndex.setSubscribeStatNum(albumStatVo.getSubscribeStatNum());
            albumInfoIndex.setBuyStatNum(albumStatVo.getBuyStatNum());
            albumInfoIndex.setCommentStatNum(albumStatVo.getCommentStatNum());
        }, threadPoolExecutor).exceptionally(ex -> {
            // 异常处理
            return null;
        });

        // 等待所有异步任务完成
        CompletableFuture.allOf(
                albumInfoCompletableFuture,
                categoryCompletableFuture,
                userCompletableFuture,
                statCompletableFuture
        ).join();
        // 将整合后的数据插入到ES中
        log.info("将数据插入到es中");
        albumIndexRepository.save(albumInfoIndex);

        //保存题词库
        SuggestIndex suggestIndex = new SuggestIndex();
        suggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndex.setKeywordPinyin(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndex.setKeywordSequence(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndexRepository.save(suggestIndex);

        SuggestIndex suggestIndexIntro = new SuggestIndex();
        suggestIndexIntro.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndexIntro.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndexIntro.setKeywordPinyin(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndexIntro.setKeywordSequence(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndexRepository.save(suggestIndexIntro);
    }

    @Override
    public void lowerAlbum(Long albumId) {
        //根据专辑的id删除es中的数据
        albumIndexRepository.deleteById(albumId);
    }

    /**
     * 根据专辑索引查询条件搜索专辑信息
     * 此方法使用Elasticsearch客户端发送搜索请求，并处理响应数据以生成搜索响应视图对象
     *
     * @param albumIndexQuery 专辑索引查询对象，包含搜索所需的各种查询参数
     * @return AlbumSearchResponseVo 搜索响应视图对象，包含搜索结果和分页信息
     * @throws IOException 当搜索请求发送过程中发生I/O错误时抛出此异常
     */
    @Override
    public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) throws IOException {
        // 构建DSL搜索请求
        SearchRequest searchRequest = this.buildQueryDsl(albumIndexQuery);
        // 执行搜索请求并获取响应
        SearchResponse<AlbumInfoIndex> searchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        // 解析搜索结果数据
        AlbumSearchResponseVo searchResponseVo = this.parseResultData(searchResponse);
        // 设置搜索结果的总记录数
        searchResponseVo.setTotal(searchResponse.hits().total().value());
        // 设置每页记录数
        searchResponseVo.setPageSize(albumIndexQuery.getPageSize());
        // 设置当前页码
        searchResponseVo.setPageNo(albumIndexQuery.getPageNo());
        // 计算并设置总页数
        searchResponseVo.setTotalPages(searchResponseVo.getTotal() % albumIndexQuery.getPageSize() == 0 ?
                searchResponseVo.getTotal() / albumIndexQuery.getPageSize() :
                searchResponseVo.getTotal() / albumIndexQuery.getPageSize() + 1);
        // 返回搜索响应视图对象
        return searchResponseVo;
    }

    /**
     * 解析搜索结果数据
     * 此方法主要用于将从搜索引擎获取的搜索结果转换为专辑搜索响应对象
     * 它处理搜索结果，将每个命中的文档转换为专辑信息索引视图对象，并处理高亮显示的标题
     *
     * @param searchResponse 搜索响应，包含命中的专辑信息索引数据
     * @return 返回一个填充了搜索结果的专辑搜索响应视图对象
     */
    private AlbumSearchResponseVo parseResultData(SearchResponse<AlbumInfoIndex> searchResponse) {
        // 创建一个专辑搜索响应视图对象，用于存储解析后的搜索结果
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();

        // 将搜索响应中的命中文档流转换为专辑信息索引视图对象列表
        List<AlbumInfoIndexVo> albumInfoIndexVoList = searchResponse.hits().hits().stream().map(hit -> {
            // 创建一个专辑信息索引视图对象，用于存储转换后的命中文档数据
            AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
            // 获取命中文档的源数据
            AlbumInfoIndex albumInfoIndex = hit.source();
            // 将源数据复制到视图对象中
            BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);

            // 如果搜索结果中包含了高亮显示的专辑标题，则更新视图对象的标题
            if (null != hit.highlight().get("albumTitle")) {
                String albumTitle = hit.highlight().get("albumTitle").get(0);
                albumInfoIndexVo.setAlbumTitle(albumTitle);
            }

            // 返回转换后的视图对象
            return albumInfoIndexVo;
        }).toList();

        // 将转换后的专辑信息索引视图对象列表设置到响应视图对象中
        albumSearchResponseVo.setList(albumInfoIndexVoList);

        // 返回填充了搜索结果的响应视图对象
        return albumSearchResponseVo;
    }

    /**
     * 根据专辑索引查询对象构建Query DSL请求
     * 该方法用于将用户查询条件转换为Elasticsearch的搜索请求
     *
     * @param albumIndexQuery 专辑索引查询对象，包含用户指定的查询条件
     * @return SearchRequest 构建的Query DSL搜索请求
     */
    private SearchRequest buildQueryDsl(AlbumIndexQuery albumIndexQuery) {
        // 创建SearchRequest构建器
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        // 设置索引名称
        searchRequestBuilder.index("albuminfo");
        // 创建BoolQuery构建器，用于组合多个查询条件
        BoolQuery.Builder boolQuerybuilder = new BoolQuery.Builder();

        // 检索入口
        if (!StringUtils.isEmpty(albumIndexQuery.getKeyword())) {
            // 构建查询条件，匹配专辑标题、简介或播音员名称中包含关键词
            boolQuerybuilder.should(s -> s.match(m -> m.field("albumTitle").query(albumIndexQuery.getKeyword())))
                    .should(s -> s.match(m -> m.field("albumIntro").query(albumIndexQuery.getKeyword())))
                    .should(s -> s.match(m -> m.field("announcerName").query(albumIndexQuery.getKeyword())));
            // 设置高亮显示
            searchRequestBuilder.highlight(h -> h.fields("albumTitle", f -> f.preTags("<span style=color:red>").postTags("</span>")));
        }

        // 根据一级分类ID构建查询条件
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory1Id())) {
            boolQuerybuilder.filter(f -> f.term(t -> t.field("category1Id").value(albumIndexQuery.getCategory1Id())));
        }

        // 根据二级分类ID构建查询条件
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory2Id())) {
            boolQuerybuilder.filter(f -> f.term(t -> t.field("category2Id").value(albumIndexQuery.getCategory2Id())));
        }

        // 根据三级分类ID构建查询条件
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory3Id())) {
            boolQuerybuilder.filter(f -> f.term(t -> t.field("category3Id").value(albumIndexQuery.getCategory3Id())));
        }

        // 根据属性列表构建查询条件
        List<String> attributeList = albumIndexQuery.getAttributeList();
        if (!CollectionUtils.isEmpty(attributeList)) {
            for (String attr : attributeList) {
                String[] split = attr.split(":");
                if (null != split && split.length == 2) {
                    // 构建嵌套查询条件，匹配属性ID和值ID
                    boolQuerybuilder.filter(f -> f.nested(n -> n.path("attributeValueIndexList")
                            .query(q -> q.bool(b -> b.must(m -> m.match(a -> a.field("attributeValueIndexList.attributeId").query(split[0])))
                                    .must(m -> m.match(a -> a.field("attributeValueIndexList.valueId").query(split[1])))

                            ))
                    ));
                }
            }
        }

        // 根据排序条件构建查询
        String order = albumIndexQuery.getOrder();
        if (!StringUtils.isEmpty(order)) {
            String[] split = order.split(":");
            String field = "";
            if (null != split && split.length == 2) {
                // 根据排序类型选择排序字段
                switch (split[0]) {
                    case "1":
                        field = "hotScore";
                        break;
                    case "2":
                        field = "playStatNum";
                        break;
                    case "3":
                        field = "createTime";
                        break;
                }
                String finalField = field;
                // 设置排序条件
                searchRequestBuilder.sort(s -> s.field(f -> f.field(finalField).order("asc".equals(split[1]) ? SortOrder.Asc : SortOrder.Desc)));
            }
        }

        // 计算分页参数
        int from = (albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize();
        searchRequestBuilder.from(from);
        searchRequestBuilder.size(albumIndexQuery.getPageSize());

        // 构建BoolQuery
        BoolQuery boolQuery = boolQuerybuilder.build();
        // 设置查询条件
        searchRequestBuilder.query(boolQuery._toQuery());

        // 构建并返回SearchRequest
        SearchRequest searchRequest = searchRequestBuilder.build();
        // 打印生成的DSL请求
        System.out.println("dsl:\t" + searchRequest.toString());
        return searchRequest;
    }

    /**
     * 根据一级分类ID获取频道数据
     * 该方法通过调用远程服务获取三级分类数据，并根据这些数据查询Elasticsearch中的专辑信息
     * 它首先获取一级分类下的所有三级分类，然后对每个三级分类查询最热门的六个专辑
     *
     * @param category1Id 一级分类ID
     * @return 返回包含三级分类及其对应热门专辑列表的Map列表
     * @throws IOException 如果与Elasticsearch的通信中发生I/O错误
     */
    @Override
    public List<Map<String, Object>> channel(Long category1Id) throws IOException {
        // 调用Feign客户端获取一级分类下的所有三级分类
        Result<List<BaseCategory3>> baseCategory3Result = categoryFeignClient.findTopBaseCategory3(category1Id);
        List<BaseCategory3> baseCategory3List = baseCategory3Result.getData();
        // 确保三级分类数据不为空
        Assert.notNull(baseCategory3List, "远程调用失败");

        // 提取所有三级分类的ID
        List<Long> category3IdList = baseCategory3List.stream().map(BaseCategory3::getId).collect(Collectors.toList());
        // 将三级分类列表转换为Map，便于后续查询
        Map<Long, BaseCategory3> category3Map = baseCategory3List.stream().collect(Collectors.toMap(BaseCategory3::getId, baseCategory3 -> baseCategory3));

        // 构建Elasticsearch搜索请求
        SearchRequest.Builder request = new SearchRequest.Builder();
        // 准备terms查询的字段值列表
        List<FieldValue> valueList = category3IdList.stream().map(category3Id -> FieldValue.of(category3Id)).collect(Collectors.toList());

        // 执行Elasticsearch搜索，查询每个三级分类下最热门的六个专辑
        SearchResponse<AlbumInfoIndex> searchResponse = elasticsearchClient.search(s -> s.index("albuminfo").query(q -> q.bool(b -> b.filter(f -> f.terms(t -> t.field("category3Id").terms(t1 -> t1.value(valueList))))))
                        .aggregations("agg_category3Id", a -> a.terms(t -> t.field("category3Id").size(10))
                                .aggregations("agg_topSix", a1 -> a1.topHits(s3 -> s3.size(6).sort(sort -> sort.field(f -> f.field("hotScore").order(SortOrder.Desc))))))
                , AlbumInfoIndex.class);

        // 处理搜索响应中的聚合结果
        Aggregate aggregate = searchResponse.aggregations().get("agg_category3Id");
        List<Map<String, Object>> listmap = aggregate.lterms().buckets().array().stream().map(bucket -> {
            Map<String, Object> map = new HashMap<>();
            long category3Id = bucket.key();
            Aggregate aggTopSix = bucket.aggregations().get("agg_topSix");

            // 解析每个三级分类下最热门的专辑
            List<AlbumInfoIndex> albumInfoIndexList = aggTopSix.topHits().hits().hits().stream().map(hit -> {
                String data = hit.source().toString();
                AlbumInfoIndex albumInfoIndex = JSONObject.parseObject(data, AlbumInfoIndex.class);
                return albumInfoIndex;
            }).collect(Collectors.toList());

            // 将三级分类信息及其对应热门专辑列表存入Map
            map.put("baseCategory3", category3Map.get(category3Id));
            map.put("list", albumInfoIndexList);
            return map;

        }).collect(Collectors.toList());

        // 返回包含所有三级分类及其热门专辑的Map列表
        return listmap;
    }

    /**
     * 提供自动补全建议的功能
     * 根据用户输入的关键词，从Elasticsearch中获取相关的补全建议
     *
     * @param keyword 用户输入的关键词
     * @return 包含补全建议的列表
     */
    @Override
    public List<String> completeSuggest(String keyword) {
        SearchResponse<SuggestIndex> searchResponse = null;
        try {
            // 执行Elasticsearch搜索，获取补全建议
            searchResponse = elasticsearchClient.search(s -> s.index("suggestinfo")
                            .suggest(s1 -> s1.suggesters("keyword-suggest", s2 -> s2
                                            .prefix(keyword)
                                            .completion(c -> c
                                                    .field("keyword")
                                                    .skipDuplicates(true)
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .size(10)))
                                    .suggesters("keywordPinyin-suggest", s2 -> s2
                                            .prefix(keyword)
                                            .completion(c -> c
                                                    .field("keywordPinyin")
                                                    .skipDuplicates(true)
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .size(10)))
                                    .suggesters("keywordSquence-suggest", s2 -> s2
                                            .prefix(keyword).completion(c -> c.
                                                    field("keywordSequence")
                                                    .skipDuplicates(true)
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .size(10)))
                            )
                    ,
                    SuggestIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 创建列表，用于存储所有的建议标题
        ArrayList<String> list = new ArrayList<>();
        // 添加从搜索响应中提取的建议标题
        list.addAll(getSuggesetionTitle(searchResponse,"keyword-suggest"));
        list.addAll(getSuggesetionTitle(searchResponse,"keywordPinyin-suggest"));
        list.addAll(getSuggesetionTitle(searchResponse,"keywordSequence-suggest"));

        // 返回包含所有建议标题的列表
        return list;
    }
    private Collection<String> getSuggesetionTitle(SearchResponse<SuggestIndex> searchResponse, String suggest) {
        List<Suggestion<SuggestIndex>> suggestionList = searchResponse.suggest().get(suggest);
        if(!CollectionUtils.isEmpty(suggestionList)){
            //循环遍历集合
            for (Suggestion<SuggestIndex> suggestIndexSuggestion : suggestionList) {
                //获取数据
                List<String> list = suggestIndexSuggestion.completion().options().stream().map(option -> {
                    String title = option.source().getTitle();
                    return title;
                }).collect(Collectors.toList());
                return list;
            };
        }

        return new ArrayList<>();
    }

    /**
     * 更新最近的专辑排名
     * 此方法通过调用远程服务获取一级分类，然后针对每个分类和排名维度，
     * 使用Elasticsearch进行搜索排序，并将结果保存到Redis中
     */
    @Override
    public void updateLatelyAlbumRanking() {
        // 调用Feign客户端获取所有一级分类
        Result<List<BaseCategory1>> baseCategory1Result =categoryFeignClient.findAllCategory1();
        // 断言调用结果不为空
        Assert.notNull(baseCategory1Result,"远程调用失败");
        // 获取一级分类列表
        List<BaseCategory1> baseCategory1List = baseCategory1Result.getData();
        // 再次断言列表不为空
        Assert.notNull(baseCategory1List,"远程调用失败");
        // 遍历一级分类列表
        for (BaseCategory1 baseCategory1 : baseCategory1List) {
            // 定义排名维度数组
            String[] rankingDimensionArray = new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
            // 遍历排名维度
            for (String ranking : rankingDimensionArray) {
                // 初始化搜索响应对象
                SearchResponse<AlbumInfoIndex> searchResponse = null;
                // 尝试执行Elasticsearch搜索
                try {
                    /*searchResponse = elasticsearchClient.search(s->s.index("albuminfo")
                            .query(q->q.term(t->t.value("category1Id").value(baseCategory1.getId())))
                                    .sort(so->so.field(d->d.field(ranking).order(SortOrder.Desc)))
                                    .size(10)
                            , AlbumInfoIndex.class);*/
                    searchResponse = elasticsearchClient.search(f -> f.index("albuminfo")
                            .query(q -> q.term(t -> t.field("category1Id").value(baseCategory1.getId())))
                            .sort(s -> s.field(d -> d.field(ranking).order(SortOrder.Desc)))
                            .size(10), AlbumInfoIndex.class);
                } catch (Exception e) {
                    // 捕获异常并抛出运行时异常
                    throw new RuntimeException(e);
                }
                // 提取搜索结果中的专辑信息
                List<AlbumInfoIndex> albumInfoIndexList = searchResponse.hits().hits().stream().map(Hit::source).collect(Collectors.toList());
                // 构造Redis中的排名键
                String rangKey = RedisConstant.RANKING_KEY_PREFIX+baseCategory1.getId();
                // 将排名维度和对应的专辑信息列表存入Redis
                redisTemplate.boundHashOps(rangKey).put(ranking,albumInfoIndexList);
            }
        }
    }

    @Override
    public List<AlbumInfoIndexVo> findRankingList(Long category1Id, String dimension) {
        return (List<AlbumInfoIndexVo>) redisTemplate.boundHashOps(RedisConstant.RANKING_KEY_PREFIX + category1Id).get(dimension);
    }
}
